package repo

import (
	"gitee.com/linxing_3/sr-core/config"
	"gitee.com/linxing_3/sr-core/domain/dao/scope"
	"gitee.com/linxing_3/sr-core/domain/repo"
	"gitee.com/linxing_3/sr-core/plugins/storage/cache"
	"gitee.com/linxing_3/sr-core/plugins/storage/database"
	"gitee.com/linxing_3/sr-core/plugins/storage/database/driver"
	"gitee.com/mkwchecking/sr-admin/apps/devtools/entity"
)

func NewSysDB(dataset database.IDataSet, cache cache.ICache) *SysDB {
	return &SysDB{
		IRepo: repo.NewSet[any](dataset, cache),
	}
}

type SysDB struct {
	repo.IRepo[any]
}

func (s *SysDB) GetTable(schema, tableName string) (*entity.DBTables, error) {
	res := &entity.DBTables{}
	var err error
	switch config.Get().Database.Driver {
	case driver.SQLite3:
		res.Schema = schema
		res.TableName = tableName
	default:
		err = s.Dao().Scan(res,
			scope.WithTable("information_schema.tables"),
			scope.Where("table_schema =?", schema),
			scope.Where("table_name =?", tableName),
			scope.WithFirst(),
		)
	}

	return res, err
}

func (s *SysDB) GetColumns(schema, tableName string) ([]*entity.DBColumns, error) {
	res := make([]*entity.DBColumns, 0)
	var err error
	switch config.Get().Database.Driver {
	case driver.SQLite3:
		sqlCols := make([]*entity.DBColumnsSqlite, 0)
		err = s.Dao().Exec("PRAGMA table_info(\"" + tableName + "\")").Scan(&sqlCols)
		if err != nil {
			return nil, err
		}
		for _, col := range sqlCols {
			nCol := &entity.DBColumns{
				TableSchema: schema,
				TableName:   tableName,
				ColumnName:  col.Name,
				DataType:    col.Type,
			}
			if col.NotNull == 1 {
				nCol.IsNullable = "NO"
			} else {
				nCol.IsNullable = "YES"
			}

			if col.Pk == 1 {
				nCol.ColumnKey = "PRI"
			} else {
				nCol.ColumnKey = ""
			}

			res = append(res, nCol)
		}
	default:
		err = s.Dao().Scan(&res,
			scope.WithTable("information_schema.COLUMNS"),
			scope.Where("TABLE_SCHEMA =?", schema),
			scope.Where("TABLE_NAME =?", tableName),
		)
	}
	return res, err
}

func (s *SysDB) GetFullTable(schema, tableName string) (*entity.DBTables, error) {
	tb, err := s.GetTable(schema, tableName)
	if err != nil {
		return nil, err
	}

	cols, err := s.GetColumns(schema, tableName)
	if err != nil {
		return nil, err
	}

	tb.Columns = cols
	return tb, nil
}
